﻿Imports IWshRuntimeLibrary
Imports Shell32

Module modWRDBTasks

    Friend Const REGAPP As String = "WRDBTasks"
    Friend swLog As IO.StreamWriter = Nothing
    Friend CurrentProject As String = ""
    Friend WithEvents Tray As NotifyIcon
    Friend LogFile As String = ""
    Friend ImportProgressForm As frmProgress = Nothing
    Friend ImportForm As frmImportScheduled = Nothing
    Friend IsCancelled As Boolean = False

    Sub Main()
        Application.EnableVisualStyles()
        Application.Run(New clsAppContext)
    End Sub

    Private Sub Tray_Click(sender As Object, e As EventArgs) Handles Tray.Click
        Dim mi As Reflection.MethodInfo = GetType(NotifyIcon).GetMethod("ShowContextMenu", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
        mi.Invoke(Tray, Nothing)
    End Sub

    Friend Sub SetTrayText(Text As String, ParamArray Args() As Object)
        Text = String.Format(Text, Args)
        Dim TrayText As String = Text
        If TrayText.Length >= 64 Then TrayText = TrayText.Substring(0, 63)
        Tray.Text = TrayText
        If ImportProgressForm IsNot Nothing Then ImportProgressForm.lblProgress.Text = Text
        Application.DoEvents()
    End Sub

    Friend Sub AppendLog(format As String, ParamArray args() As String)
        swLog = New IO.StreamWriter(LogFile, True)
        swLog.WriteLine(Now.ToString("yyyy/MM/dd HH:mm:ss") & vbTab & StringFormat(format, args))
        swLog.Close()
        swLog.Dispose()
    End Sub

    Friend Sub Progress(ByRef DB As DBProviders.clsDB, Value As Long, MaxValue As Long, ProgressText As String)
        With ImportProgressForm
            If Value = -1 Then
                .ProgressBar1.Style = ProgressBarStyle.Marquee
                .lblProgress.Text = ProgressText
                .Refresh()
                Application.DoEvents()
            Else
                .ProgressBar1.Style = ProgressBarStyle.Blocks
                Static lastPct As Integer = -1
                Dim pct As Integer = CInt(Value * 100.0 / MaxValue)
                .lblProgress.Text = ProgressText
                If pct <> lastPct Then
                    .Text = String.Format("WRDB Task Progress - {0}%", pct)
                    .ProgressBar1.Value = pct
                    IsCancelled = .IsCancelled
                    If DB IsNot Nothing Then DB.Cancelled = .IsCancelled
                    lastPct = pct
                End If
                .Refresh()
                Application.DoEvents()
            End If
        End With
    End Sub

    Public Function ShortCutExists(ShortcutName As String, Folder As Environment.SpecialFolder) As Boolean
        Try
            If IO.File.Exists(Environment.GetFolderPath(Folder) & "\" & ShortcutName & ".lnk") Then
                Return True
            Else
                Return False
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message)
            Return True
        End Try
    End Function

    Public Sub DeleteShortCut(ShortcutName As String, Folder As Environment.SpecialFolder)
        Try
            If ShortCutExists(ShortcutName, Folder) Then IO.File.Delete(Environment.GetFolderPath(Folder) & "\" & ShortcutName & ".lnk")
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub

    Public Sub CreateShortcut(ShortcutName As String, FullAppPath As String, Folder As Environment.SpecialFolder)
        Dim Shell As New WshShell
        Dim Shortcut As IWshShortcut
        'Shell = CreateObject("WScript.Shell")
        Shortcut = Shell.CreateShortcut(Environment.GetFolderPath(Folder) & "\" & ShortcutName & ".lnk")
        With Shortcut
            .TargetPath = FullAppPath
            .Description = ShortcutName
            .IconLocation = "" & FullAppPath & ", 0"""
            .WindowStyle = 1
            .Save()
        End With
    End Sub

    'NOTE: following were copied out of modCommon in WRDBLib because it causes other conflicts

    ''' <summary>
    ''' Name of directory where data will be stored by default (My Documents>\WRDB)
    ''' </summary>
    ''' <remarks></remarks>
    Friend Function MyDataPath() As String
        Dim s As String = My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\WRDB"
        If Not My.Computer.FileSystem.DirectoryExists(s) Then My.Computer.FileSystem.CreateDirectory(s)
        Return s
    End Function

    ''' <summary>
    ''' Test object; if dbnull, nothing, empty string, minimum value, or NAN return default value
    ''' </summary>
    Friend Function TestNull(ByVal Value As Object, ByVal DefaultValue As Object) As Object
        If IsDBNull(Value) OrElse
            IsNothing(Value) OrElse
            (TypeOf Value Is String AndAlso String.IsNullOrEmpty(Value)) OrElse
            (TypeOf Value Is Date AndAlso Value = DateTime.MinValue) OrElse
            (IsNumeric(Value) AndAlso Value = Single.MinValue) OrElse
            (TypeOf Value Is Single AndAlso Single.IsNaN(Value)) OrElse
            (TypeOf Value Is Double AndAlso Double.IsNaN(Value)) Then Return DefaultValue Else Return Value
    End Function

    ''' <summary>
    ''' Display warning or question dialog box
    ''' </summary>
    ''' <param name="WarningText">Main text of dialog box; may have additional text added depending on other arguments; note that following text transformations occur: \n=NewLine; \t=Tab; \b=Bullet. If text contains question mark, will use OK/Cancel buttons and question icon; otherwise will use OK button and warning icon</param>
    ''' <param name="SQLString">Text containing SQL statement text. If present, adds text showing the SQL string</param>
    ''' <param name="ex">Exception; if present, adds text showing exception message</param>
    ''' <param name="ShowRetryCancel">If true, will change buttons to Retry/Cancel and prompt that database/table may be locked and allow user to retry later (caller must loop)</param>
    ''' <param name="Caption">Messagebox caption</param>
    Public Function WarningMsg(WarningText As String, Optional SQLString As String = "", Optional ex As Exception = Nothing, Optional ShowRetryCancel As Boolean = False, Optional Caption As String = "WRDB Warning") As DialogResult
        Dim errmsg As String = WarningText
        If SQLString <> "" Then errmsg &= "\n\nThe SQL statement was:\n\n" & SQLString
        If ex IsNot Nothing Then errmsg &= "\n\nThe error message was:\n\n" & ex.Message
        Dim btn As MessageBoxButtons
        Dim icon As MessageBoxIcon
        If ShowRetryCancel Then
            errmsg &= "\n\nIf the database or table is locked, you can click Retry in a moment to try the query again."
            btn = MessageBoxButtons.RetryCancel
            icon = MessageBoxIcon.Exclamation
        ElseIf errmsg.Contains("?") Then
            btn = MessageBoxButtons.OKCancel
            icon = MessageBoxIcon.Question
        Else
            btn = MessageBoxButtons.OK
            icon = MessageBoxIcon.Warning
        End If
        Return MessageBox.Show(StringFormat(errmsg.Replace(vbCrLf, vbCr)), Caption, btn, icon)
    End Function

    ''' <summary>
    ''' Provide string.format functionality and substitute \n for vbCr, \t for vbTab, and \b for bullet character, \\ for \
    ''' </summary>
    ''' <param name="FormatString">String to format (\n is newline and \t is tab, etc.)</param>
    ''' <param name="Arguments">Format arguments</param>
    Friend Function StringFormat(FormatString As String, ParamArray Arguments() As Object) As String
        Dim s As String
        If Arguments.Length = 0 Then s = FormatString Else s = String.Format(FormatString, Arguments)
        s = s.Replace("\\", Chr(1))
        s = s.Replace("\n", vbCr).Replace("\t", vbTab).Replace("\b", "•")
        Return s.Replace(Chr(1), "\")
    End Function

    ''' <summary>
    ''' Display unhandled error form in a separate thread
    ''' </summary>
    ''' <param name="ErrorText">Text to display on error form</param>
    ''' <param name="ex">Exception object</param>
    Public Sub ErrorMsg(Optional ErrorText As String = "", Optional ex As Exception = Nothing)
        Beep()
#If Project = "WRDBLIB" Then
        If Project IsNot Nothing AndAlso Project.DB IsNot Nothing Then Project.DB.LastException = Nothing
        If MainWRDB IsNot Nothing Then MainWRDB.CloseSplashScreen()
#End If
        Application.UseWaitCursor = False
        Application.DoEvents()

        'following is test to avoid STA threading error messages when copying to clipboard
        Dim t As New Threading.Thread(AddressOf LaunchErrorForm)
        t.SetApartmentState(Threading.ApartmentState.STA)
        t.Start(New Object() {ErrorText, ex})
        While t.IsAlive
            Application.DoEvents()
            Threading.Thread.Sleep(500)
        End While
    End Sub

    Private Sub LaunchErrorForm(Args() As Object)
        With New frmError(Args(0), Args(1))
            .BringToFront()
            .ShowDialog()
        End With
    End Sub

    'NOTE: following were copied out of clsWRDBSettings.vb in WRDBProject because I want to use this REGAPP value

    Friend Enum enumTaskKey
        BackupActivated
        Folder
        BackupTime
        AllProjects
        LastWarned

        LastConnection
        NumConnections
        ConnectionName
        ConnectionType
        ImportActivated
        ImportFolder
        ImportTime
        WRDBProjectName
        WRDBTable
        MinDays
        MaxDays
        DatabaseType
        ServerName
        DatabaseName
        UserName
        Password
        SourceTable
        MappingFile
        APIVer
        Activated
        Resample
        ResampleInterval
        IncrementalPrecip
        OverrideDateRange
        FirstDate
        LastDate
    End Enum

    ''' <summary>
    ''' Save application key to registry (section is "Settings")
    ''' </summary>
    ''' <param name="Key">Predefined key</param>
    ''' <param name="KeyText">Value</param>
    Friend Sub SetKey(Key As enumTaskKey, KeyText As String)
        SaveSetting(REGAPP, "Settings", Key.ToString, KeyText)
    End Sub

    ''' <summary>
    ''' Get application key from registry (section is "Settings")
    ''' </summary>
    ''' <param name="Key">Predefined key</param>
    ''' <param name="DefaultKeyText">Default Value</param>
    Friend Function GetKey(Key As enumTaskKey, DefaultKeyText As String) As String
        Return GetSetting(REGAPP, "Settings", Key.ToString, DefaultKeyText)
    End Function

    ''' <summary>
    ''' Save application key to registry
    ''' </summary>
    ''' <param name="Key">Predefined key</param>
    ''' <param name="KeyText">Value</param>
    Friend Sub SetKey(Section As String, Key As enumTaskKey, KeyText As String)
        SaveSetting(REGAPP, Section, Key.ToString, KeyText)
    End Sub

    ''' <summary>
    ''' Get application key from registry
    ''' </summary>
    ''' <param name="Key">Predefined key</param>
    ''' <param name="DefaultKeyText">Default Value</param>
    Friend Function GetKey(Section As String, Key As enumTaskKey, DefaultKeyText As String) As String
        Return GetSetting(REGAPP, Section, Key.ToString, DefaultKeyText)
    End Function

End Module
